var gulp = require('gulp');
var nodemon = require('gulp-nodemon');
// 调用 .create() 意味着你得到一个唯一的实例并允许您创建多个服务器或代理。 
var browserSync = require('browser-sync').create();
var concat = require('gulp-concat');//合并javascript
var lessConvert = require('gulp-less');
const rename = require('gulp-rename')
var pageConfig = require('./page-config');
var path = require('path');
var postCss = require('gulp-postcss');
var autoprefixer = require('autoprefixer');
var ejsConvert = require('gulp-ejs');
var copy = require('gulp-copy');
var root = path.join(__dirname, './');

// 遍历配置文件
function handlePaths(extName, cb, fn) {
    count = 0;
    var end = function () {
        count++;
        if (count >= pageConfig.pages.length) cb();
    };
    for (var i in pageConfig.pages) {
        var paths = [];
        const page = pageConfig.pages[i];
        const jsName = page.page || page.vendor;

        if (page.components && page.components.length !== 0) {
            // 页面相关组件js
            for (var j in page.components) {
                const comp = page.components[j]
                const base = comp.base || '/src/views';
                if (comp.blocks && comp.blocks.length) {
                    comp.blocks.forEach(block => {
                        if (typeof block === 'string') {
                            paths.push(path.join(root, base, block, `/**/*.${extName}`))
                        } else if (typeof block === 'object') {
                            getDeepPath(block, paths, extName, path.join(root, base))
                        }
                    })
                }
            }
        }
        // 页面入口
        const jsBase = page.entryFolder || path.join('/src/views', jsName);
        if (page.files && page.files[extName]) {
            page.files[extName].forEach(file => {
                paths.push(path.join(root, jsBase, `/${file}.${extName}`));
            })
        } else {
            paths.push(path.join(root, jsBase, `/*.${extName}`));
        }
        const output = page.output && page.output[extName] ? page.output[extName] : pageConfig.defaultOutput;
        const distPath = path.join(path.resolve(root, `${pageConfig.tempStatic}`), `${output}`);
        const javaPath = path.join(path.resolve(root, `${pageConfig.javaStatic}`), `${output}`);
        let outputFormat;
        fn(paths, jsName, distPath, javaPath, end, outputFormat)
    }
}
// 遍历配置文件
function handleEjsPaths(extName, cb, fn) {
    count = 0;
    var end = function () {
        count++;
        if (count >= pageConfig.pages.length) cb();
    };
    for (var i in pageConfig.pages) {
        var devPaths = [], prodPaths = [];
        const page = pageConfig.pages[i];
        const jsName = page.page || page.vendor;
        // 页面入口
        const jsBase = page.entryFolder || path.join('/src/views', jsName);
        devPaths.push(path.join(root, jsBase, `/${page.entryFile.dev}.${extName}`));
        prodPaths.push(path.join(root, jsBase, `/${page.entryFile.prod}.${extName}`));
        const output = page.output && page.output[extName] ? page.output[extName] : pageConfig.defaultOutput;
        const distPath = path.join(path.resolve(root, `${pageConfig.tempStatic}`), `${output}`);
        const javaPath = path.join(path.resolve(root, `${pageConfig.javaStatic}`), `${output}`);
        let outputFormat = page.ejsFormat || '.html';
        fn(devPaths, prodPaths, jsName, distPath, javaPath, end, outputFormat)
    }
}
function getDeepPath(block, paths, extName, base) {
    if (block.name) {
        if (block.files && block.files[extName]) {
            block.files[extName].forEach(blo => {
                paths.push(path.join(base, block.name, `/${blo}.${extName}`))
            })
        } else {
            paths.push(path.join(base, block.name, `/*.${extName}`))
        }
        if (block.blocks) {
            block.blocks.forEach(blo => {
                if (typeof blo === 'string') {
                    paths.push(path.join(base, block.name, blo, `/**/*.${extName}`))
                } else if (typeof blo === 'object') {
                    getDeepPath(blo, paths, extName, path.join(base, block.name))
                }
            })
        }
    }
}
// 拷贝静态文件
function static(cb) {
    if (pageConfig.publishSource && pageConfig.publishSource.length) {
        gulp.src(pageConfig.publishSource)
            .pipe(copy(pageConfig.publishPath, { prefix: 1 }))
            .pipe(gulp.dest(path.join(root, pageConfig.publishPath)))
            .on('end', () => {
                cb()
            })
    } else {
        cb()
    }
}

// 根据配置合并js
function js(cb) {
    handlePaths('js', cb, (paths, fileName, filePath, javaPath, end) => {
        gulp.src(paths)
            .pipe(concat({ path: fileName + '.js' }))
            .pipe(gulp.dest(filePath))
            .pipe(gulp.dest(javaPath))
            .on("end", end);
    })
};
var plugins = [
    autoprefixer({ overrideBrowserslist: ["> 1%", "last 2 versions", "not ie <=8"] })
]
// 合并less
function less(cb) {
    handlePaths('less', cb, (paths, fileName, filePath, javaPath, end) => {
        gulp.src(paths)
            .pipe(lessConvert())
            .pipe(concat({ path: fileName + '.css' }))
            .pipe(postCss(plugins))
            .pipe(gulp.dest(filePath))
            .pipe(gulp.dest(javaPath))
            .on("end", end);
    })
};

// ejs转换为html或jsp等
function ejs(cb) {
    handleEjsPaths('ejs', cb, (devPaths, prodPaths, fileName, filePath, javaPath, end, outputFormat) => {
        gulp.src(devPaths[0])
            .pipe(ejsConvert({}))
            .pipe(rename(p => {
                p.basename = fileName
                p.extname = outputFormat || '.html'
            }))
            .pipe(gulp.dest(filePath))
            .on("end", end);

        gulp.src(prodPaths[0])
            .pipe(ejsConvert({}))
            .pipe(rename(p => {
                p.basename = fileName
                p.extname = '.jsp'
            }))
            .pipe(gulp.dest(javaPath))
            .on("end", end);
    })
};

// 运行服务并监听项目文件
function serve(cb) {
    let buildFiles = gulp.parallel('js', 'less', 'ejs');
    browserSync.init({
        proxy: pageConfig.serverProxy || 'http://127.0.0.1:3000/',
        files: [`${pageConfig.tempStatic}/**/*.*`],
        port: 8080
    }, () => {
        console.log('browser refreshed.');
    })
    let watcher = gulp.watch('src/**/*.*')
    nodemon({
        script: './bin/www',
        ignore: [
            'gulpfile.js',
            'node_modules/',
            'public/**/*.*',
            `${pageConfig.tempStatic}/**/*.*`,
            `${pageConfig.javaStatic}/**/*.*`],
        env: { 'NODE_ENV': 'development' }
    }).on('start', () => {
        console.log('nodemon refresh')
        buildFiles();
        watcher.close()
        watcher = gulp.watch('src/**/*.*')
        watcher.on('change', () => {
            buildFiles();
        });
    }).on('crash', () => {
        console.log('nodemon 崩溃了！');
        watcher.close();
        cb()
    }).on('exit', () => {
        watcher.close();
        cb()
    })

}

function otherserve(cb) {
    browserSync.init({
        proxy: pageConfig.serverProxy || 'http://127.0.0.1:3000/',
        files: [`${pageConfig.tempStatic}/**/*.*`],
        port: 8081
    }, () => {
        console.log('browser refreshed.');
    })
    let buildFiles = gulp.parallel('js', 'less', 'ejs');
    let watcher = gulp.watch('src/**/*.*')
    watcher.on('change', () => {
        buildFiles();
    });
    cb()
}

// 打包
function build(cbbuild) {
    const fn = gulp.series('js', 'less', 'ejs', 'static', (cb) => {
        console.log('打包完成！')
        cb()
    })
    fn()
    cbbuild()
    console.log('打包完成！')
}

exports.serve = serve
exports.less = less
exports.js = js
exports.ejs = ejs
exports.static = static
exports.build = build;
exports.otherserve = otherserve;
